
//Deriche模糊与高斯滤波接近、与半径大小无关
//用于大半径模糊的场景（半径较小时、高斯滤波速度更快）
//http://en.wikipedia.org/wiki/Deriche_edge_detector

#include "Process.h"
using namespace std;
using namespace cv;


void Deriche(cv::Mat& img, cv::Mat* outimg, double aph)
{
	double alpha = aph;
	double exalpha = exp(-alpha);
	double exalpha2 = exp(-2 * alpha);
	double kr = ((1 - exalpha) * (1 - exalpha)) / (1 + 2 * alpha * exalpha - exalpha2);
	double a1 = kr;
	double a2 = kr * exalpha * (alpha - 1);
	double a3 = kr * exalpha * (alpha + 1);
	double a4 = -kr * exalpha2;
	double b1 = 2 * exalpha;
	double b2 = -exalpha2;
	double c1 = 1.0;
	double c2 = 1.0;

	//边界部分需要除以2

	int row = img.rows;
	int col = img.cols;
	Mat floatimg;
	img.convertTo(floatimg, CV_32FC1);
	Mat midImg(img.size(), CV_32FC1);

	Mat disp = floatimg.clone();

	float RTF1, RTF2, RTF3;
	for (int i = 0; i < row; i++)
	{
		float* ptrtmp = midImg.ptr<float>(i, 0);
		float* ptrimg = floatimg.ptr<float>(i, 0);
		RTF3 = *(ptrimg) * (a1 + a2 + b1 + b2) / 2;
		RTF2 = *(ptrimg + 1) * a1 / 2 + *(ptrimg)*a2 / 2 + RTF3 * (b1 + b2);
		for (int j = 2; j < col; j++)
		{
			RTF1 = *(ptrimg + j) * a1 + *(ptrimg + j - 1) * a2 + RTF2 * b1 + RTF3 * b2;
			*(ptrtmp + j) = RTF1;
			RTF3 = RTF2;
			RTF2 = RTF1;
		}
	}
	for (int i = 0; i < row; i++)
	{
		float* ptrtmp = midImg.ptr<float>(i, 0);
		float* ptrimg = floatimg.ptr<float>(i, 0);
		RTF3 = *(ptrimg + col - 1) * (a1 + a2 + b1 + b2) / 2;
		RTF2 = *(ptrimg + col - 2) * a1 / 2 + *(ptrimg + col - 1) * a2 / 2 + RTF3 * (b1 + b2);
		for (int j = col - 3; j > -1; j--)
		{
			RTF1 = *(ptrimg + j + 1) * a3 + *(ptrimg + j + 2) * a4 + RTF2 * b1 + RTF3 * b2;
			RTF3 = RTF2;
			RTF2 = RTF1;
			*(ptrtmp + j) = c1 * (*(ptrtmp + j) + RTF1);
		}
	}
	for (int j = 0; j < col; j++)
	{
		RTF3 = midImg.at<float>(0, j) * (a1 + a2 + b1 + b2) / 2;
		RTF2 = midImg.at<float>(1, j) * a1 / 2 + midImg.at<float>(0, j) * a2 / 2 + RTF3 * (b1 + b2);
		for (int i = 2; i < row; i++)
		{
			RTF1 = midImg.at<float>(i, j) * a1 + midImg.at<float>(i - 1, j) * a2 + RTF2 * b1 + RTF3 * b2;
			RTF3 = RTF2;
			RTF2 = RTF1;
			floatimg.at<float>(i, j) = RTF1;
		}
		floatimg.at<float>(0, j) = floatimg.at<float>(1, j);
	}
	for (int j = 0; j < col; j++)
	{
		RTF3 = midImg.at<float>(row - 1, j) * (a1 + a2 + b1 + b2) / 2;
		RTF2 = midImg.at<float>(row - 2, j) * a1 / 2 + midImg.at<float>(row - 1, j) * a2 / 2 + RTF3 * (b1 + b2);
		for (int i = row - 3; i > -1; i--)
		{
			RTF1 = midImg.at<float>(i + 1, j) * a3 + midImg.at<float>(i + 2, j) * a4 + RTF2 * b1 + RTF3 * b2;
			RTF3 = RTF2;
			RTF2 = RTF1;
			floatimg.at<float>(i, j) = c2 * (floatimg.at<float>(i, j) + RTF1);
			disp.at<float>(i, j) = RTF1;
		}
	}
	floatimg.convertTo(*outimg, CV_8UC1);
}

void DericheSpeed(cv::Mat& img, cv::Mat* outimg, double aph)
{
	//判断输入地址与输出地址是否相同
	Mat Outimage;
	bool TypeVal = GetValt(img, outimg, Outimage);

	float alpha = aph;
	float exalpha = exp(-alpha);
	float exalpha2 = exp(-2 * alpha);
	float kr = ((1 - exalpha) * (1 - exalpha)) / (1 + 2 * alpha * exalpha - exalpha2);
	float a1 = kr;
	float a2 = kr * exalpha * (alpha - 1);
	float a3 = kr * exalpha * (alpha + 1);
	float a4 = -kr * exalpha2;
	float b1 = 2 * exalpha;
	float b2 = -exalpha2;
	float c1 = 1.0;
	float c2 = 1.0;

	float startA = (a1 + a2 + b1 + b2) / 2;
	float startB = (b1 + b2);
	float a1h = a1 / 2;
	float a2h = a2 / 2;

	__m256 ma1 = _mm256_set1_ps(a1);
	__m256 ma2 = _mm256_set1_ps(a2);
	__m256 ma3 = _mm256_set1_ps(a3);
	__m256 ma4 = _mm256_set1_ps(a4);

	int row = img.rows;
	int col = img.cols;
	Mat floatimg(img.size(), CV_32FC1);
	int countCol = (col / 8) * 8;
	int countRow = (row / 8) * 8;
	int bcol = col - 7;
	int brow = row - 7;

	__m256 RTF1, RTF2, RTF3, FRT;
	__m256 LTF1, LTF2, LTF3;
	float rft1, rft2, rft3;
	__m256 mb1 = _mm256_set1_ps(b1);
	__m256 mb2 = _mm256_set1_ps(b2);

	Mat Line(floatimg.cols, 8, CV_32FC1);
	Mat LineResa(floatimg.cols, 8, CV_32FC1);
	Mat LineResb(floatimg.cols, 8, CV_32FC1);
	//水平方向
	for (int i = 0; i < brow; i += 8)
	{
		uchar* ptr1 = img.ptr<uchar>(i, 0);
		uchar* ptr2 = img.ptr<uchar>(i + 1, 0);
		uchar* ptr3 = img.ptr<uchar>(i + 2, 0);
		uchar* ptr4 = img.ptr<uchar>(i + 3, 0);
		uchar* ptr5 = img.ptr<uchar>(i + 4, 0);
		uchar* ptr6 = img.ptr<uchar>(i + 5, 0);
		uchar* ptr7 = img.ptr<uchar>(i + 6, 0);
		uchar* ptr8 = img.ptr<uchar>(i + 7, 0);
		float* LinePtr = Line.ptr<float>(0);
		//读取8位灰度图、转置(使内存地址连续)、并转换为浮点格式
		for (size_t j = 0; j < bcol; j += 8)
		{
			__m128i va0 = _mm_loadl_epi64((__m128i*)(ptr1 + j));
			__m128i va1 = _mm_loadl_epi64((__m128i*)(ptr2 + j));
			__m128i va2 = _mm_loadl_epi64((__m128i*)(ptr3 + j));
			__m128i va3 = _mm_loadl_epi64((__m128i*)(ptr4 + j));
			__m128i va4 = _mm_loadl_epi64((__m128i*)(ptr5 + j));
			__m128i va5 = _mm_loadl_epi64((__m128i*)(ptr6 + j));
			__m128i va6 = _mm_loadl_epi64((__m128i*)(ptr7 + j));
			__m128i va7 = _mm_loadl_epi64((__m128i*)(ptr8 + j));

			__m128i S01 = _mm_unpacklo_epi8(va0, va1);
			__m128i S23 = _mm_unpacklo_epi8(va2, va3);
			__m128i S0123L = _mm_unpacklo_epi16(S01, S23);
			__m128i S0123H = _mm_unpackhi_epi16(S01, S23);
			__m128i S45 = _mm_unpacklo_epi8(va4, va5);
			__m128i S67 = _mm_unpacklo_epi8(va6, va7);
			__m128i S4567L = _mm_unpacklo_epi16(S45, S67);
			__m128i S4567H = _mm_unpackhi_epi16(S45, S67);

			__m128i T0 = _mm_unpacklo_epi32(S0123L, S4567L);
			__m128i T1 = _mm_unpackhi_epi32(S0123L, S4567L);
			__m128i T2 = _mm_unpacklo_epi32(S0123H, S4567H);
			__m128i T3 = _mm_unpackhi_epi32(S0123H, S4567H);

			_mm256_storeu_ps(LinePtr + (j) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(T0)));
			_mm256_storeu_ps(LinePtr + (j + 1) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_srli_si128(T0, 8))));
			_mm256_storeu_ps(LinePtr + (j + 2) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(T1)));
			_mm256_storeu_ps(LinePtr + (j + 3) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_srli_si128(T1, 8))));
			_mm256_storeu_ps(LinePtr + (j + 4) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(T2)));
			_mm256_storeu_ps(LinePtr + (j + 5) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_srli_si128(T2, 8))));
			_mm256_storeu_ps(LinePtr + (j + 6) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(T3)));
			_mm256_storeu_ps(LinePtr + (j + 7) * 8, _mm256_cvtepi32_ps(_mm256_cvtepu8_epi32(_mm_srli_si128(T3, 8))));
		}
		//行尾非整数部分
		for (size_t k = 0; k < 8; k++)
		{
			int cont = k + i;
			for (size_t m = bcol; m < col; m++)
			{
				Line.at<float>(m, k) = img.at<uchar>(cont, m);
			}
		}

		//正向处理
		RTF3 = _mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(0)), _mm256_set1_ps(startA));
		RTF2 = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(1)), _mm256_set1_ps(a1h)), _mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(0)), _mm256_set1_ps(a2h))),
			_mm256_mul_ps(RTF3, _mm256_set1_ps(startB)));
		_mm256_storeu_ps(LineResa.ptr<float>(0), RTF3);
		_mm256_storeu_ps(LineResa.ptr<float>(1), RTF2);
		for (size_t j = 2; j < col; j++)
		{
			__m256 addtmp1 = _mm256_add_ps(_mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(j)), ma1), _mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(j - 1)), ma2));
			__m256 addtmp2 = _mm256_add_ps(_mm256_mul_ps(RTF2, mb1), _mm256_mul_ps(RTF3, mb2));
			RTF1 = _mm256_add_ps(addtmp1, addtmp2);
			RTF3 = RTF2;
			RTF2 = RTF1;
			_mm256_storeu_ps(LineResa.ptr<float>(j), RTF1);
		}

		//反向处理
		LTF3 = _mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(Line.rows - 1)), _mm256_set1_ps(startA));
		LTF2 = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(Line.rows - 2)), _mm256_set1_ps(a1h)), _mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(Line.rows - 1)), _mm256_set1_ps(a2h))),
			_mm256_mul_ps(LTF3, _mm256_set1_ps(startB)));
		_mm256_storeu_ps(LineResb.ptr<float>(col - 2), LTF2);
		_mm256_storeu_ps(LineResb.ptr<float>(col - 1), LTF3);
		for (int j = col - 3; j > -1; j--)
		{
			__m256 addtmp1 = _mm256_add_ps(_mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(j + 1)), ma1), _mm256_mul_ps(_mm256_load_ps(Line.ptr<float>(j + 2)), ma2));
			__m256 addtmp2 = _mm256_add_ps(_mm256_mul_ps(LTF2, mb1), _mm256_mul_ps(LTF3, mb2));
			LTF1 = _mm256_add_ps(addtmp1, addtmp2);
			LTF3 = LTF2;
			LTF2 = LTF1;
			_mm256_storeu_ps(LineResb.ptr<float>(j), LTF1);
		}
		//结果叠加
		for (size_t j = 0; j < bcol; j += 8)
		{
			{
				__m256 sum0 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j)), _mm256_load_ps(LineResb.ptr<float>(j)));
				__m256 sum1 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j + 1)), _mm256_load_ps(LineResb.ptr<float>(j + 1)));
				__m256 sum2 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j + 2)), _mm256_load_ps(LineResb.ptr<float>(j + 2)));
				__m256 sum3 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j + 3)), _mm256_load_ps(LineResb.ptr<float>(j + 3)));
				__m256i S01 = _mm256_unpacklo_epi32(_mm256_castps_si256(sum0), _mm256_castps_si256(sum1));
				__m256i S23 = _mm256_unpacklo_epi32(_mm256_castps_si256(sum2), _mm256_castps_si256(sum3));
				__m256i M01 = _mm256_unpackhi_epi32(_mm256_castps_si256(sum0), _mm256_castps_si256(sum1));
				__m256i M23 = _mm256_unpackhi_epi32(_mm256_castps_si256(sum2), _mm256_castps_si256(sum3));
				__m256i S0123L = _mm256_unpacklo_epi64(S01, S23);
				__m256i S0123H = _mm256_unpackhi_epi64(S01, S23);
				__m256i M0123L = _mm256_unpacklo_epi64(M01, M23);
				__m256i M0123H = _mm256_unpackhi_epi64(M01, M23);
				_mm256_storeu2_m128(floatimg.ptr<float>(i, j), floatimg.ptr<float>(i + 1, j), _mm256_castsi256_ps(S0123L));
				_mm256_storeu2_m128(floatimg.ptr<float>(i + 2, j), floatimg.ptr<float>(i + 3, j), _mm256_castsi256_ps(S0123H));
				_mm256_storeu2_m128(floatimg.ptr<float>(i + 4, j), floatimg.ptr<float>(i + 5, j), _mm256_castsi256_ps(M0123L));
				_mm256_storeu2_m128(floatimg.ptr<float>(i + 6, j), floatimg.ptr<float>(i + 7, j), _mm256_castsi256_ps(M0123H));

			}
			__m256 sum4 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j + 4)), _mm256_load_ps(LineResb.ptr<float>(j + 4)));
			__m256 sum5 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j + 5)), _mm256_load_ps(LineResb.ptr<float>(j + 5)));
			__m256 sum6 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j + 6)), _mm256_load_ps(LineResb.ptr<float>(j + 6)));
			__m256 sum7 = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(j + 7)), _mm256_load_ps(LineResb.ptr<float>(j + 7)));
			__m256i S45 = _mm256_unpacklo_epi32(_mm256_castps_si256(sum4), _mm256_castps_si256(sum5));
			__m256i S67 = _mm256_unpacklo_epi32(_mm256_castps_si256(sum6), _mm256_castps_si256(sum7));
			__m256i M45 = _mm256_unpackhi_epi32(_mm256_castps_si256(sum4), _mm256_castps_si256(sum5));
			__m256i M67 = _mm256_unpackhi_epi32(_mm256_castps_si256(sum6), _mm256_castps_si256(sum7));
			__m256i S4567L = _mm256_unpacklo_epi64(S45, S67);
			__m256i S4567H = _mm256_unpackhi_epi64(S45, S67);
			__m256i M4567L = _mm256_unpacklo_epi64(M45, M67);
			__m256i M4567H = _mm256_unpackhi_epi64(M45, M67);
			_mm256_storeu2_m128(floatimg.ptr<float>(i, j + 4), floatimg.ptr<float>(i + 1, j + 4), _mm256_castsi256_ps(S4567L));
			_mm256_storeu2_m128(floatimg.ptr<float>(i + 2, j + 4), floatimg.ptr<float>(i + 3, j + 4), _mm256_castsi256_ps(S4567H));
			_mm256_storeu2_m128(floatimg.ptr<float>(i + 4, j + 4), floatimg.ptr<float>(i + 5, j + 4), _mm256_castsi256_ps(M4567L));
			_mm256_storeu2_m128(floatimg.ptr<float>(i + 6, j + 4), floatimg.ptr<float>(i + 7, j + 4), _mm256_castsi256_ps(M4567H));
		}
		//叠加非整数部分
		for (size_t m = bcol; m < col; m++)
		{
			__m256 sum = _mm256_add_ps(_mm256_load_ps(LineResa.ptr<float>(m)), _mm256_load_ps(LineResb.ptr<float>(m)));
			for (size_t n = 0; n < 8; n++)
			{
				floatimg.at<float>(n + i, m) = sum.m256_f32[n];
			}
		}
	}
	//水平非整数部分
	float* forwSig = new float[col];
	for (size_t i = countRow; i < row; i++)
	{
		//水平向左
		forwSig[0] = img.at<uchar>(i, 0) * startA;
		forwSig[1] = img.at<uchar>(i, 1) * a1h + img.at<uchar>(i, 0) * a2h + forwSig[0] * startB;
		for (int j = 2; j < col; j++)
		{
			forwSig[j] = img.at<uchar>(i, j) * a1 + img.at<uchar>(i, j - 1) * a2 + forwSig[j - 1] * b1 + forwSig[j - 2] * b2;
		}
		//水平向右
		rft3 = img.at<uchar>(i, col - 1) * startA;
		rft2 = img.at<uchar>(i, col - 2) * a1h + img.at<uchar>(i, col - 1) * a2 / 2 + rft3 * startB;
		for (int j = col - 3; j > -1; j--)
		{
			rft1 = img.at<uchar>(i, j + 1) * a3 + img.at<uchar>(i, j + 2) * a4 + rft2 * b1 + rft3 * b2;
			rft3 = rft2;
			rft2 = rft1;
			floatimg.at<float>(i, j) = rft1 + forwSig[j];//叠加结果
		}
	}

	//垂直方向
	Mat Cath(floatimg.rows, 8, CV_32FC1);
	for (int j = 0; j < bcol; j += 8)
	{
		//正向
		float* p0 = floatimg.ptr<float>(0, j);
		float* p1 = floatimg.ptr<float>(1, j);
		FRT = _mm256_load_ps(p1);
		RTF3 = _mm256_mul_ps(_mm256_load_ps(p0), _mm256_set1_ps(startA));
		RTF2 = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(FRT, _mm256_set1_ps(a1h)), _mm256_mul_ps(_mm256_load_ps(p0), _mm256_set1_ps(a2h))),
			_mm256_mul_ps(RTF3, _mm256_set1_ps(startB)));
		_mm256_store_ps(Cath.ptr<float>(0, 0), RTF3);
		_mm256_store_ps(Cath.ptr<float>(1, 0), RTF2);
		for (int i = 2; i < row; i++)
		{
			float* ptr = floatimg.ptr<float>(i, j);
			__m256 MULF = _mm256_mul_ps(FRT, ma2);
			FRT = _mm256_load_ps(ptr);
			RTF1 = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(FRT, ma1), MULF),
				_mm256_add_ps(_mm256_mul_ps(RTF2, mb1), _mm256_mul_ps(RTF3, mb2)));
			RTF3 = RTF2;
			RTF2 = RTF1;
			_mm256_store_ps(Cath.ptr<float>(i, 0), RTF1);
		}
		//反向
		float* p2 = floatimg.ptr<float>(row - 1, j);
		float* p3 = floatimg.ptr<float>(row - 2, j);
		FRT = _mm256_load_ps(p2);
		RTF3 = _mm256_mul_ps(FRT, _mm256_set1_ps(startA));
		RTF2 = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(_mm256_load_ps(p3), _mm256_set1_ps(a1h)), _mm256_mul_ps(FRT, _mm256_set1_ps(a2h))),
			_mm256_mul_ps(RTF3, _mm256_set1_ps(startB)));
		__m256i ints = _mm256_cvtps_epi32(_mm256_add_ps(RTF3, _mm256_load_ps(Cath.ptr<float>(row - 1, 0))));
		__m256i intsa = _mm256_packs_epi32(ints, ints);
		__m256i tmps = _mm256_set_epi64x(intsa.m256i_i64[3], intsa.m256i_i64[1], intsa.m256i_i64[2], intsa.m256i_i64[0]);
		__m128i intsb = _mm_packus_epi16(_mm256_castsi256_si128(tmps), _mm256_castsi256_si128(tmps));
		_mm_storeu_si64(Outimage.ptr<uchar>(row - 1, j), intsb);
		ints = _mm256_cvtps_epi32(_mm256_add_ps(RTF2, _mm256_load_ps(Cath.ptr<float>(row - 2, 0))));
		intsa = _mm256_packs_epi32(ints, ints);
		tmps = _mm256_set_epi64x(intsa.m256i_i64[3], intsa.m256i_i64[1], intsa.m256i_i64[2], intsa.m256i_i64[0]);
		intsb = _mm_packus_epi16(_mm256_castsi256_si128(tmps), _mm256_castsi256_si128(tmps));
		_mm_storeu_si64(Outimage.ptr<uchar>(row - 2, j), intsb);
		for (int i = row - 3; i > -1; i--)
		{
			float* ptr = floatimg.ptr<float>(i + 1, j);
			__m256 MULF = _mm256_mul_ps(FRT, ma2);
			FRT = _mm256_load_ps(ptr);
			RTF1 = _mm256_add_ps(_mm256_add_ps(_mm256_mul_ps(FRT, ma3), MULF),
				_mm256_add_ps(_mm256_mul_ps(RTF2, mb1), _mm256_mul_ps(RTF3, mb2)));
			RTF3 = RTF2;
			RTF2 = RTF1;
			__m256i ints = _mm256_cvtps_epi32(_mm256_add_ps(RTF1, _mm256_load_ps(Cath.ptr<float>(i, 0))));
			__m256i intsa = _mm256_packs_epi32(ints, ints);
			__m256i tmps = _mm256_set_epi64x(intsa.m256i_i64[3], intsa.m256i_i64[1], intsa.m256i_i64[2], intsa.m256i_i64[0]);
			__m128i intsb = _mm_packus_epi16(_mm256_castsi256_si128(tmps), _mm256_castsi256_si128(tmps));
			_mm_storeu_si64(Outimage.ptr<uchar>(i, j), intsb);
		}
	}
	//垂直非整数部分
	if (countCol < col)
	{
		int step = col - countCol;
		float* oner = new float[row * step];
		float RTF1, RTF2, RTF3;
		for (int j = countCol; j < col; j++)//处理非整数部分
		{
			int tmp = j - countCol;
			//正向
			RTF3 = floatimg.at<float>(0, j) * startA;
			RTF2 = floatimg.at<float>(1, j) * a1h + floatimg.at<float>(0, j) * a2h + RTF3 * startB;
			for (int i = 2; i < row; i++)
			{
				RTF1 = floatimg.at<float>(i, j) * a1 + floatimg.at<float>(i - 1, j) * a2 + RTF2 * b1 + RTF3 * b2;
				RTF3 = RTF2;
				RTF2 = RTF1;
				*(oner + step * i + tmp) = RTF1;
			}
			*(oner + tmp) = RTF3;
			*(oner + step + tmp) = RTF2;
			//反向
			RTF3 = floatimg.at<float>(row - 1, j) * startA;
			RTF2 = floatimg.at<float>(row - 2, j) * a1h + floatimg.at<float>(row - 1, j) * a2h + RTF3 * startB;
			for (int i = row - 3; i > -1; i--)
			{
				RTF1 = floatimg.at<float>(i + 1, j) * a3 + floatimg.at<float>(i + 2, j) * a4 + RTF2 * b1 + RTF3 * b2;
				RTF3 = RTF2;
				RTF2 = RTF1;
				Outimage.at<uchar>(i, j) = (*(oner + step * i + tmp) + RTF1);
			}
		}
		delete[] oner;
	}


	//输入地址与输出地址相同时
	if (TypeVal)
	{
		*outimg = Outimage;
	}
}
